using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using System.Text.RegularExpressions;
using System.Text.Json;

namespace JGSY.CMS.LowCode.Platform.Application.Services
{
    /// <summary>
    /// 产品应用服务实现
    /// </summary>
    public class ProductAppService : IProductAppService
    {
        private readonly IProductRepository _productRepository;
        private readonly ILogger<ProductAppService> _logger;

        /// <summary>
        /// 构造函数，注入必要的依赖服务
        /// </summary>
        /// <param name="productRepository">产品仓储</param>
        /// <param name="logger">日志服务</param>
        public ProductAppService(IProductRepository productRepository, ILogger<ProductAppService> logger)
        {
            _productRepository = productRepository;
            _logger = logger;
        }

        /// <summary>
        /// 获取所有产品
        /// </summary>
        /// <returns>产品列表</returns>
        public async Task<IEnumerable<ProductDto>> GetAllAsync()
        {
            try
            {
                _logger.LogInformation("获取所有产品");
                
                var products = await _productRepository.GetAllAsync();
                return products.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取所有产品时发生错误");
                throw;
            }
        }

        /// <summary>
        /// 根据ID获取产品
        /// </summary>
        /// <param name="id">产品ID</param>
        /// <returns>产品信息</returns>
        public async Task<ProductDto?> GetByIdAsync(long id)
        {
            try
            {
                _logger.LogInformation("根据ID获取产品, ID: {Id}", id);
                
                var product = await _productRepository.GetByIdAsync(id);
                return product != null ? MapToDto(product) : null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据ID获取产品时发生错误, ID: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 根据SKU获取产品
        /// </summary>
        /// <param name="sku">产品SKU</param>
        /// <returns>产品信息</returns>
        public async Task<ProductDto?> GetBySkuAsync(string sku)
        {
            try
            {
                _logger.LogInformation("根据SKU获取产品, SKU: {Sku}", sku);
                
                var product = await _productRepository.GetBySkuAsync(sku);
                return product != null ? MapToDto(product) : null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据SKU获取产品时发生错误, SKU: {Sku}", sku);
                throw;
            }
        }

        /// <summary>
        /// 根据别名获取产品
        /// </summary>
        /// <param name="slug">产品别名</param>
        /// <returns>产品信息</returns>
        public async Task<ProductDto?> GetBySlugAsync(string slug)
        {
            try
            {
                _logger.LogInformation("根据别名获取产品, Slug: {Slug}", slug);
                
                var product = await _productRepository.GetBySlugAsync(slug);
                return product != null ? MapToDto(product) : null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据别名获取产品时发生错误, Slug: {Slug}", slug);
                throw;
            }
        }

        /// <summary>
        /// 根据分类获取产品列表
        /// </summary>
        /// <param name="categoryId">分类ID</param>
        /// <returns>产品列表</returns>
        public async Task<IEnumerable<ProductDto>> GetByCategoryAsync(long categoryId)
        {
            try
            {
                _logger.LogInformation("根据分类获取产品, CategoryID: {CategoryId}", categoryId);
                
                var products = await _productRepository.GetByCategoryAsync(categoryId);
                return products.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据分类获取产品时发生错误, CategoryID: {CategoryId}", categoryId);
                throw;
            }
        }

        /// <summary>
        /// 获取推荐产品
        /// </summary>
        /// <param name="count">数量限制</param>
        /// <returns>推荐产品列表</returns>
        public async Task<IEnumerable<ProductDto>> GetFeaturedProductsAsync(int count = 10)
        {
            try
            {
                _logger.LogInformation("获取推荐产品, Count: {Count}", count);
                
                var products = await _productRepository.GetFeaturedProductsAsync(count);
                return products.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取推荐产品时发生错误, Count: {Count}", count);
                throw;
            }
        }

        /// <summary>
        /// 获取热销产品
        /// </summary>
        /// <param name="count">数量限制</param>
        /// <returns>热销产品列表</returns>
        public async Task<IEnumerable<ProductDto>> GetBestSellingProductsAsync(int count = 10)
        {
            try
            {
                _logger.LogInformation("获取热销产品, Count: {Count}", count);
                
                var products = await _productRepository.GetBestSellingProductsAsync(count);
                return products.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取热销产品时发生错误, Count: {Count}", count);
                throw;
            }
        }

        /// <summary>
        /// 获取最新产品
        /// </summary>
        /// <param name="count">数量限制</param>
        /// <returns>最新产品列表</returns>
        public async Task<IEnumerable<ProductDto>> GetLatestProductsAsync(int count = 10)
        {
            try
            {
                _logger.LogInformation("获取最新产品, Count: {Count}", count);
                
                var products = await _productRepository.GetLatestProductsAsync(count);
                return products.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取最新产品时发生错误, Count: {Count}", count);
                throw;
            }
        }

        /// <summary>
        /// 获取低库存产品
        /// </summary>
        /// <param name="threshold">库存阈值</param>
        /// <returns>低库存产品列表</returns>
        public async Task<IEnumerable<ProductDto>> GetLowStockProductsAsync(int threshold = 10)
        {
            try
            {
                _logger.LogInformation("获取低库存产品, Threshold: {Threshold}", threshold);
                
                var products = await _productRepository.GetLowStockProductsAsync(threshold);
                return products.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取低库存产品时发生错误, Threshold: {Threshold}", threshold);
                throw;
            }
        }

        /// <summary>
        /// 分页获取产品列表
        /// </summary>
        public async Task<(IEnumerable<ProductDto> Items, int TotalCount)> GetPagedAsync(int pageIndex, int pageSize, string? keyword = null, long? categoryId = null, byte? status = null, decimal? minPrice = null, decimal? maxPrice = null, string? sortBy = null, bool sortDesc = false)
        {
            try
            {
                _logger.LogInformation("分页获取产品列表, PageIndex: {PageIndex}, PageSize: {PageSize}", pageIndex, pageSize);
                
                var (items, totalCount) = await _productRepository.GetPagedAsync(
                    pageIndex, 
                    pageSize, 
                    keyword, 
                    categoryId, 
                    status, 
                    minPrice, 
                    maxPrice, 
                    sortBy, 
                    sortDesc);
                
                return (items.Select(MapToDto), totalCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分页获取产品列表时发生错误");
                throw;
            }
        }

        /// <summary>
        /// 创建产品
        /// </summary>
        /// <param name="productDto">产品信息</param>
        /// <returns>创建的产品</returns>
        public async Task<ProductDto> CreateAsync(ProductDto productDto)
        {
            try
            {
                _logger.LogInformation("创建产品, 产品名称: {Name}", productDto.Name);
                
                // 检查SKU是否已存在
                if (await _productRepository.SkuExistsAsync(productDto.Sku))
                {
                    throw new InvalidOperationException($"SKU '{productDto.Sku}' 已存在");
                }
                
                // 检查Slug是否已存在
                if (!string.IsNullOrEmpty(productDto.Slug) && await _productRepository.SlugExistsAsync(productDto.Slug))
                {
                    throw new InvalidOperationException($"别名 '{productDto.Slug}' 已存在");
                }
                
                // 将DTO映射为实体
                var product = MapToEntity(productDto);
                
                // 设置创建时间
                product.CreatedAt = DateTime.UtcNow;
                product.UpdatedAt = DateTime.UtcNow;
                
                // 保存产品
                await _productRepository.AddAsync(product);
                
                // 获取最新数据并返回
                var createdProduct = await _productRepository.GetBySkuAsync(product.Sku ?? string.Empty);
                return createdProduct != null ? MapToDto(createdProduct) : new ProductDto { Id = 0, Name = "创建失败" };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建产品时发生错误, 产品名称: {Name}", productDto.Name);
                throw;
            }
        }

        /// <summary>
        /// 更新产品
        /// </summary>
        /// <param name="productDto">产品信息</param>
        /// <returns>更新的产品</returns>
        public async Task<ProductDto> UpdateAsync(ProductDto productDto)
        {
            try
            {
                _logger.LogInformation("更新产品, 产品ID: {Id}", productDto.Id);
                
                // 检查产品是否存在
                var existingProduct = await _productRepository.GetByIdAsync(productDto.Id);
                if (existingProduct == null)
                {
                    throw new InvalidOperationException($"产品ID '{productDto.Id}' 不存在");
                }
                
                // 检查SKU是否已存在（排除当前产品）
                if (await _productRepository.SkuExistsAsync(productDto.Sku, productDto.Id))
                {
                    throw new InvalidOperationException($"SKU '{productDto.Sku}' 已被其他产品使用");
                }
                
                // 检查Slug是否已存在（排除当前产品）
                if (!string.IsNullOrEmpty(productDto.Slug) && await _productRepository.SlugExistsAsync(productDto.Slug, productDto.Id))
                {
                    throw new InvalidOperationException($"别名 '{productDto.Slug}' 已被其他产品使用");
                }
                
                // 更新产品信息
                var product = MapToEntity(productDto);
                
                // 保留原始数据
                product.CreatedAt = existingProduct.CreatedAt;
                product.CreatedBy = existingProduct.CreatedBy;
                
                // 更新修改时间
                product.UpdatedAt = DateTime.UtcNow;
                
                // 增加版本号
                product.Version = existingProduct.Version + 1;
                
                // 保存更新
                await _productRepository.UpdateAsync(product);
                
                // 获取最新数据并返回
                var updatedProduct = await _productRepository.GetByIdAsync(product.Id);
                return updatedProduct != null ? MapToDto(updatedProduct) : new ProductDto { Id = product.Id, Name = "更新失败" };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新产品时发生错误, 产品ID: {Id}", productDto.Id);
                throw;
            }
        }

        /// <summary>
        /// 删除产品
        /// </summary>
        /// <param name="id">产品ID</param>
        /// <returns>是否删除成功</returns>
        public async Task<bool> DeleteAsync(long id)
        {
            try
            {
                _logger.LogInformation("删除产品, 产品ID: {Id}", id);
                
                // 检查产品是否存在
                var product = await _productRepository.GetByIdAsync(id);
                if (product == null)
                {
                    _logger.LogWarning("删除产品失败，产品不存在, 产品ID: {Id}", id);
                    return false;
                }
                
                // 执行删除
                await _productRepository.DeleteAsync(id);
                
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除产品时发生错误, 产品ID: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 批量删除产品
        /// </summary>
        /// <param name="ids">产品ID列表</param>
        /// <returns>删除的数量</returns>
        public async Task<int> BatchDeleteAsync(IEnumerable<long> ids)
        {
            try
            {
                _logger.LogInformation("批量删除产品, 产品ID列表: {Ids}", string.Join(",", ids));
                
                // 执行批量删除
                var deletedCount = await _productRepository.BatchDeleteAsync(ids);
                
                return deletedCount;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量删除产品时发生错误, 产品ID列表: {Ids}", string.Join(",", ids));
                throw;
            }
        }

        /// <summary>
        /// 更新产品状态
        /// </summary>
        /// <param name="id">产品ID</param>
        /// <param name="status">状态</param>
        /// <returns>是否更新成功</returns>
        public async Task<bool> UpdateStatusAsync(long id, byte status)
        {
            try
            {
                _logger.LogInformation("更新产品状态, 产品ID: {Id}, 状态: {Status}", id, status);
                
                // 检查产品是否存在
                var product = await _productRepository.GetByIdAsync(id);
                if (product == null)
                {
                    _logger.LogWarning("更新产品状态失败，产品不存在, 产品ID: {Id}", id);
                    return false;
                }
                
                // 验证状态值是否有效
                if (status > 3) // 假设状态值范围是0-3
                {
                    throw new ArgumentOutOfRangeException(nameof(status), "无效的状态值");
                }
                
                // 更新产品
                product.Status = status;
                product.UpdatedAt = DateTime.UtcNow;
                product.Version += 1;
                
                // 保存更新
                await _productRepository.UpdateAsync(product);
                
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新产品状态时发生错误, 产品ID: {Id}, 状态: {Status}", id, status);
                throw;
            }
        }

        /// <summary>
        /// 更新产品库存
        /// </summary>
        /// <param name="id">产品ID</param>
        /// <param name="stock">库存数量</param>
        /// <returns>是否更新成功</returns>
        public async Task<bool> UpdateStockAsync(long id, int stock)
        {
            try
            {
                _logger.LogInformation("更新产品库存, 产品ID: {Id}, 库存: {Stock}", id, stock);
                
                if (stock < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(stock), "库存不能为负数");
                }
                
                return await _productRepository.UpdateStockAsync(id, stock);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新产品库存时发生错误, 产品ID: {Id}, 库存: {Stock}", id, stock);
                throw;
            }
        }

        /// <summary>
        /// 增加产品库存
        /// </summary>
        /// <param name="id">产品ID</param>
        /// <param name="quantity">增加数量</param>
        /// <returns>是否更新成功</returns>
        public async Task<bool> IncreaseStockAsync(long id, int quantity)
        {
            try
            {
                _logger.LogInformation("增加产品库存, 产品ID: {Id}, 数量: {Quantity}", id, quantity);
                
                if (quantity <= 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(quantity), "增加的库存必须大于0");
                }
                
                return await _productRepository.IncreaseStockAsync(id, quantity);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "增加产品库存时发生错误, 产品ID: {Id}, 数量: {Quantity}", id, quantity);
                throw;
            }
        }

        /// <summary>
        /// 减少产品库存
        /// </summary>
        /// <param name="id">产品ID</param>
        /// <param name="quantity">减少数量</param>
        /// <returns>是否更新成功</returns>
        public async Task<bool> DecreaseStockAsync(long id, int quantity)
        {
            try
            {
                _logger.LogInformation("减少产品库存, 产品ID: {Id}, 数量: {Quantity}", id, quantity);
                
                if (quantity <= 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(quantity), "减少的库存必须大于0");
                }
                
                // 获取当前库存
                var product = await _productRepository.GetByIdAsync(id);
                if (product == null)
                {
                    _logger.LogWarning("减少产品库存失败，产品不存在, 产品ID: {Id}", id);
                    return false;
                }
                
                // 检查库存是否足够
                if (product.Stock < quantity)
                {
                    throw new InvalidOperationException($"库存不足，当前库存: {product.Stock}, 请求减少: {quantity}");
                }
                
                // 执行减少操作
                return await _productRepository.DecreaseStockAsync(id, quantity);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "减少产品库存时发生错误, 产品ID: {Id}, 数量: {Quantity}", id, quantity);
                throw;
            }
        }

        /// <summary>
        /// 增加产品销量
        /// </summary>
        /// <param name="id">产品ID</param>
        /// <param name="quantity">销售数量</param>
        /// <returns>是否更新成功</returns>
        public async Task<bool> IncrementSalesCountAsync(long id, int quantity = 1)
        {
            try
            {
                _logger.LogInformation("增加产品销量, 产品ID: {Id}, 数量: {Quantity}", id, quantity);
                
                if (quantity <= 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(quantity), "销售数量必须大于0");
                }
                
                return await _productRepository.IncrementSalesCountAsync(id, quantity);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "增加产品销量时发生错误, 产品ID: {Id}, 数量: {Quantity}", id, quantity);
                throw;
            }
        }

        /// <summary>
        /// 检查产品SKU是否存在
        /// </summary>
        /// <param name="sku">产品SKU</param>
        /// <param name="excludeId">排除的产品ID</param>
        /// <returns>是否存在</returns>
        public async Task<bool> SkuExistsAsync(string sku, long? excludeId = null)
        {
            try
            {
                _logger.LogInformation("检查产品SKU是否存在, SKU: {Sku}, 排除ID: {ExcludeId}", sku, excludeId);
                
                return await _productRepository.SkuExistsAsync(sku, excludeId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查产品SKU是否存在时发生错误, SKU: {Sku}, 排除ID: {ExcludeId}", sku, excludeId);
                throw;
            }
        }

        /// <summary>
        /// 检查产品别名是否存在
        /// </summary>
        /// <param name="slug">产品别名</param>
        /// <param name="excludeId">排除的产品ID</param>
        /// <returns>是否存在</returns>
        public async Task<bool> SlugExistsAsync(string slug, long? excludeId = null)
        {
            try
            {
                _logger.LogInformation("检查产品别名是否存在, Slug: {Slug}, 排除ID: {ExcludeId}", slug, excludeId);
                
                return await _productRepository.SlugExistsAsync(slug, excludeId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查产品别名是否存在时发生错误, Slug: {Slug}, 排除ID: {ExcludeId}", slug, excludeId);
                throw;
            }
        }

        /// <summary>
        /// 搜索产品
        /// </summary>
        /// <param name="keyword">搜索关键词</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <returns>搜索结果</returns>
        public async Task<(IEnumerable<ProductDto> Items, int TotalCount)> SearchAsync(string keyword, int pageIndex = 1, int pageSize = 20)
        {
            try
            {
                _logger.LogInformation("搜索产品, 关键词: {Keyword}, 页码: {PageIndex}, 页大小: {PageSize}", keyword, pageIndex, pageSize);
                
                var (items, totalCount) = await _productRepository.SearchAsync(keyword, pageIndex, pageSize);
                return (items.Select(MapToDto), totalCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "搜索产品时发生错误, 关键词: {Keyword}", keyword);
                throw;
            }
        }

        /// <summary>
        /// 获取产品统计信息
        /// </summary>
        /// <returns>统计信息</returns>
        public async Task<object> GetStatisticsAsync()
        {
            try
            {
                _logger.LogInformation("获取产品统计信息");
                
                // 获取全部产品
                var allProducts = await _productRepository.GetAllAsync();
                
                // 计算统计信息
                var statistics = new
                {
                    TotalCount = allProducts.Count(),
                    OutOfStock = allProducts.Count(p => p.Stock <= 0),
                    LowStock = allProducts.Count(p => p.Stock > 0 && p.Stock <= 10),
                    Active = allProducts.Count(p => p.Status == 1), // 上架状态
                    Inactive = allProducts.Count(p => p.Status == 0), // 下架状态
                    PreOrder = allProducts.Count(p => p.Status == 2), // 预售状态
                    SoldOut = allProducts.Count(p => p.Status == 3), // 售罄状态
                    AveragePrice = allProducts.Any() ? allProducts.Average(p => p.Price) : 0,
                    TotalValue = allProducts.Sum(p => p.Price * p.Stock),
                    BestSelling = allProducts.OrderByDescending(p => p.SalesCount).Take(5).Select(MapToDto),
                    MostViewed = allProducts.OrderByDescending(p => p.ViewCount).Take(5).Select(MapToDto)
                };
                
                return statistics;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取产品统计信息时发生错误");
                throw;
            }
        }

        /// <summary>
        /// 将产品实体映射为DTO
        /// </summary>
        /// <param name="entity">产品实体</param>
        /// <returns>产品DTO</returns>
        private ProductDto MapToDto(Product entity)
        {
            if (entity == null)
            {
                return new ProductDto { Id = 0, Name = "未找到产品" };
            }
            
            var dto = new ProductDto
            {
                Id = entity.Id,
                Name = entity.Name,
                Sku = entity.Sku ?? string.Empty,
                Slug = entity.Slug,
                Description = entity.Summary,
                Content = entity.Description,
                CategoryId = entity.CategoryId,
                Price = entity.Price,
                OriginalPrice = entity.OriginalPrice,
                CostPrice = entity.CostPrice,
                Stock = entity.Stock,
                SalesCount = entity.SalesCount,
                Status = entity.Status,
                Version = entity.Version,
                CreatedBy = entity.CreatedBy,
                UpdatedBy = entity.UpdatedBy,
                CreatedAt = entity.CreatedAt,
                UpdatedAt = entity.UpdatedAt,
                SortOrder = entity.SortOrder,
                Tags = entity.Tags,
                Images = entity.Images,
                Attributes = entity.Attributes,
                SeoTitle = entity.SeoTitle,
                SeoKeywords = entity.SeoKeywords,
                SeoDescription = entity.SeoDescription
            };
            
            // 提取主图片URL
            if (!string.IsNullOrEmpty(entity.Images))
            {
                try
                {
                    var images = JsonSerializer.Deserialize<string[]>(entity.Images);
                    dto.MainImageUrl = images?.Length > 0 ? images[0] : null;
                }
                catch
                {
                    // 解析失败时不设置主图片URL
                }
            }
            
            // 设置相关字段
            if (entity.Creator != null)
            {
                dto.CreatorName = entity.Creator.Username;
            }
            
            if (entity.Updater != null)
            {
                dto.UpdaterName = entity.Updater.Username;
            }
            
            return dto;
        }

        /// <summary>
        /// 将DTO映射为产品实体
        /// </summary>
        /// <param name="dto">产品DTO</param>
        /// <returns>产品实体</returns>
        private Product MapToEntity(ProductDto dto)
        {
            if (dto == null)
            {
                return new Product { Name = "无效数据" };
            }
            
            var entity = new Product
            {
                Id = dto.Id,
                Name = dto.Name,
                Sku = dto.Sku,
                Slug = dto.Slug,
                Summary = dto.Description,
                Description = dto.Content,
                CategoryId = dto.CategoryId,
                Price = dto.Price,
                OriginalPrice = dto.OriginalPrice,
                CostPrice = dto.CostPrice,
                Stock = dto.Stock,
                SalesCount = dto.SalesCount,
                Status = dto.Status,
                Version = dto.Version,
                CreatedBy = dto.CreatedBy,
                UpdatedBy = dto.UpdatedBy,
                CreatedAt = dto.CreatedAt,
                UpdatedAt = dto.UpdatedAt,
                SortOrder = dto.SortOrder,
                Tags = dto.Tags,
                Images = dto.Images,
                Attributes = dto.Attributes,
                SeoTitle = dto.SeoTitle,
                SeoKeywords = dto.SeoKeywords,
                SeoDescription = dto.SeoDescription
            };
            
            return entity;
        }
    }
}
